#pragma once
#include <mp/mpcomplex.h>
#include <cfloat>
mp_complex i(0, 1);
mp_complex ni(0, -1);


mp_complex_temp cosh(const mp_complex& value){
	mp_real real = cos(value.imag) * cosh(value.real);
	mp_real imag = sin(value.imag) * sinh(value.real);
	mp_complex ret (real, imag);
	return ret.toTempAndDestroy();
}

mp_complex_temp sinh(const mp_complex& value){
	mp_real real = sinh(value.real) * cos(value.imag);
	mp_real imag = sin(value.imag) * cosh(value.real);
	mp_complex ret (real, imag);
	return ret.toTempAndDestroy();
}

mp_complex_temp tan(const mp_complex& value){
	return sin(value)/cos(value);
}

mp_complex_temp tanh(const mp_complex& value){
	return sinh(value)/cosh(value);
}  

mp_complex_temp asin(const mp_complex& value){
	return ni * log(i * value + sqrt(1.0 - value * value));
}

mp_complex_temp asinh(const mp_complex& value){
	mp_complex ret = log(sqrt(1.0 + value * value) - value);
	return -ret;
} 

mp_complex_temp acos(const mp_complex& value){
	return ni * log(value + i * sqrt(1.0 - value * value));
}

mp_complex_temp acosh(const mp_complex& value){
	return 2 * log((sqrt(((value + 1.0) / 2.0)) + sqrt((value - 1.0) / 2.0)));
} 

mp_complex_temp atan(const mp_complex& value){
	mp_complex test = value * i;
	if( test.imag == 00 && (test.real == 1.0 || test.real == -1.0)){
		return mp_complex(DBL_MAX, DBL_MAX).toTempAndDestroy();
	}

	return (1.0 / (i * 2.0)) * (log((1.0 + i * value)) - log((1.0 - i * value)));
}

mp_complex_temp atanh(const mp_complex& value){
	if( value.imag == 00 && (value.real == 1.0 || value.real == -1.0)){
		return mp_complex(DBL_MAX, DBL_MAX).toTempAndDestroy();
	}

	return .5 * (log(1.0 + value) - log(1.0 - value));
} 

